"use strict";
// MVVM对象声明
var View = /** @class */ (function () {
    function View(option) {
        var vm = this;
        this.$options = option;
        // this.$el = document.querySelector(option.el);
        this.$methods = option.methods;
        // reactive
        this.$data = defineReactive(option.data);
        // touch
        Object.keys(option.methods).forEach(function (key) { return effect(option.methods[key].bind(vm)); });
    }
    return View;
}());
// ----->依赖
// 依赖类定义
var Deps = /** @class */ (function () {
    function Deps() {
        this.subscribers = []; // 初始化订阅者列表
    }
    // 添加数据的依赖
    Deps.prototype.depend = function () {
        // 保证订阅者的唯一性且只记录函数运行时的依赖
        if (Deps.runtimeTarget instanceof Function && !this.subscribers.includes(Deps.runtimeTarget)) {
            this.subscribers.push(Deps.runtimeTarget);
        }
    };
    // 更新所有依赖
    Deps.prototype.notify = function () {
        this.subscribers.forEach(function (sub) { return sub(); });
    };
    Deps.runtimeTarget = null; // 正在运行的函数
    return Deps;
}());
// 收集运行时依赖函数
function effect(eff) {
    Deps.runtimeTarget = eff;
    Deps.runtimeTarget();
    Deps.runtimeTarget = null;
}
// ----->观察
// 响应式对象方法定义
function defineReactive(obj) {
    var propMap = new Map(); // 依赖存储，属性名-->依赖列表
    return new Proxy(obj, {
        get: function (obj, key, receiver) {
            if (!propMap.get(key))
                propMap.set(key, new Deps()); // 如果该属性没有依赖列表就创建新的依赖列表
            propMap.get(key).depend(); // 添加当前依赖
            return Reflect.get(obj, key, receiver);
        },
        set: function (obj, key, value, receiver) {
            var res = Reflect.set(obj, key, value, receiver); // 记得先设置Reflect,值才会更新
            if (propMap.get(key))
                propMap.get(key).notify(); // 如果存在依赖列表，就更新触发所有依赖
            return res;
        }
    });
}
// 测试用例
var total3 = 0;
var myApp = new View({
    el: "#app",
    data: {
        price: 15,
        quatity: 20
    },
    methods: {
        calPrice: function () {
            total3 = this.$data.price * this.$data.quatity;
        }
    }
});
console.log(total3); // 300
myApp.$data.price = 20;
console.log(total3); // 400
myApp.$data.quatity = 40;
console.log(total3); // 800
// 方法变成的也是响应式的
